#ifndef GAMEPLAY_PLAY_H
#define GAMEPLAY_PLAY_H


#include "Engine/Visual.h"
#include "Engine/Reason.h"
#include "Engine/Resource/Graphic.h"
#include "Engine/Synaptic/Misc.h"
#include "SDL.h"
#include "Engine/Kinetic/Movement.h"
#include "Engine/Kinetic/Animation.h"
#include "GameState/DataStorage.h"
#include "Engine/Sense.h"
#include "Gameplay/Board.h"
#include <list>
#include <string>

namespace Engine { class Backbone; } 
namespace Gameplay { class Piece; } 
namespace GameState { namespace Endgame { class Endgame; }  } 
namespace Engine { namespace Synaptic { class Sound; }  } 

namespace Gameplay {

// Display properly the preview of the next piece, resizing and slicing as necessary
class PiecePreview : public Engine::Visual, public Engine::Reason {
  public:
	PiecePreview(const Engine::Resource::Graphic & targetGraphic, const Misc::Frame & previewFrame, const Misc::Frame & pieceFrame, int pieceID = 0); 
	~PiecePreview(); 
	virtual Engine::Resource::GraphicList display(); 
	void setPiece(int pieceID); 
	virtual void pulse(int delta); // Sets the pieceID for the preview

  private:
	Sint32 piece; 
	Engine::Resource::Graphic previewShadow; 
	Engine::Resource::Graphic boardGraphic; // Holds the resized graphic for the board
	const Misc::Frame pieceFrame; 
	const Misc::Frame previewFrame; 
	Engine::Kinetic::Movement boardMovement; 
};
// Keeps track of the score along with its rules
class Score : public Engine::Visual, public Engine::Reason {
  private:
	double maxScore; 
	double score; 
	Engine::Resource::Graphic scorebaseGraphic; 
	Engine::Resource::Graphic pointerGraphic; 
	Misc::Frame scoreFrame; 
	Engine::Kinetic::Movement pointerMovement; 
	Engine::Kinetic::Animation flashAnimation; 
	Engine::Resource::Graphic bonusTimeGfx; 
	Engine::Kinetic::Animation bonusTimeAnimation; 
	Engine::Resource::Graphic minusTimeGfx; 
	Engine::Kinetic::Animation minusTimeAnimation; 

  public:
	Score(const Misc::Frame & scoreFrame, double maxScore = 0.0f); 
	~Score(); 
	virtual Engine::Resource::GraphicList display(); 
	virtual void pulse(int delta); 
	inline double hit(double amount = 1.0f); 
	inline double miss(double amount = 1.0f); 
	double getScore(); 
};
inline double Score::hit(double amount) {
  	score += amount;
	//if (score > maxScore) maxScore = score;
	pointerMovement.setDestination(Misc::Vector2d(score, 0.0f));
	if (amount >= 5.0) bonusTimeAnimation.setFrame(0);
	return score;
	//pointerGraphic.rotate(-amount);
}

inline double Score::miss(double amount) {
  	score -= amount;
	if (score <= 0.0f) score = 0.0f;
	pointerMovement.setDestination(Misc::Vector2d(score, 0.0f));
	if (amount >= 1.0) 	minusTimeAnimation.setFrame(0);
	return score;
	//pointerGraphic.rotate(amount);
}

class Play : public Engine::Sense, public Engine::Reason, public Engine::Visual {
  private:
	Engine::Resource::Graphic targetGraphic; 
	Board board; // The current board
	std::list<Piece*> pieces; // List of falling/fitted pieces
	Engine::Resource::Graphic gfx; 
	Engine::Resource::Graphic osd; 
	Engine::Resource::Graphic boardPreview; 
	Misc::Frame boardFrame; 
	Misc::Frame pieceFrame; 
	Sint32 nextPiece; 
	PiecePreview piecePreview; 
	Engine::Resource::Graphic pauseLayer; 
	Score score; 
	Sint32 nextMoveIn; // When the piece will go down.
	bool gameOver; 
	bool pausedGame; 

  public:
	Play(std::string targetGraphicName, int boardWidth = 10, int boardHeight = 5, int pieceWidth = 50, int pieceHeight = 50); 
	~Play(); 
	virtual void pulse(int delta); 
	virtual void keyUp(SDLKey sym, SDLMod mod, Uint16 unicode); 
	inline virtual void exit(); 
	virtual Engine::Resource::GraphicList display(); 
	bool isOver(); 
	inline bool isPaused(); 
	inline bool setPaused(bool pausedStatus); 
};
inline void Play::exit() {
}

inline bool Play::isPaused() {
	return pausedGame;
}

inline bool Play::setPaused(bool pausedStatus) {
	return (pausedGame = pausedStatus);
}


} // namespace Gameplay
#endif
